/******************************************************************
 * Author: DO HOANG HAI
 * Date of creation:
 * Date of last modification: 2nd/Sep/2007
 * 
 * Description: This class provides generate functions for handling
 * and manipulate an item object as well as its representation data
 * in the database.
 ******************************************************************/


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Pbdms.Common;
using System.Xml.XPath;
using Pbdms.Common.DataObject;


namespace Pbdms.DataAccess.DataProvider
{
    interface IItemProviderInterface : IProviderInterface
    {
        Item selectFromDB();
        
    }
    /// <summary>
    /// provides means of manipulating an item object as well as ist representation data in database
    /// </summary>
    public class ItemProvider : IItemProviderInterface
    {
        private const String FILENAME = "item.xml";
        private Item itemObj;
        
        public ItemProvider(Item itemObj)
        {
            this.itemObj = itemObj;
        }
        public ItemProvider(String id)
        {
            itemObj = new Item(id);
        }

        /// <summary>
        /// create an ItemProvider object for handling this item object
        /// </summary>
        /// <param name="itemObj"></param>
        /// <returns></returns>
        public static ItemProvider create(Item itemObj)
        {
            return new ItemProvider(itemObj );
        }
        /// <summary>
        /// create a new Item object and ist ItemProvider
        /// </summary>
        /// <param name="id"></param>
        /// <param name="bPrivate"></param>
        /// <returns></returns>
        public static ItemProvider create(String id)
        {
            return new ItemProvider(id);
        }

        /// <summary>
        /// get the XPath to this item in database
        /// </summary>
        /// <returns></returns>
        private String getXPath()
        {
            return "/root/Item[@id='" + itemObj.Id + "']";
        }
        
        /// <summary>
        /// update an element to database
        /// remark: the element must be a leave node
        /// </summary>
        /// <param name="name">name of the element</param>
        /// <param name="value">value of the element</param>      
        public void updateElementToDB(String name, Object value) 
        {
            XmlHelper.create(FILENAME).updateTypedElement(getXPath() + "/" + name, value);
        }

        /// <summary>
        /// update database with new values of attributes
        /// </summary>
        public void updateAllToDB()
        {
            if (itemObj.BPrivate)
                XmlHelper.create(FILENAME).updateTypedElement(getXPath() + "/private" , 1);
            else
                XmlHelper.create(FILENAME).updateTypedElement(getXPath() + "/private", 0);

            //get id of the category
            String catId = CategoryProvider.create().getCatIdByCatName(itemObj.Category);
            XmlHelper.create(FILENAME).updateUnTypedElement(getXPath() + "/category", catId);

            //delete old elements from database
            XmlHelper.create(FILENAME).deleteRange(getXPath()+"/category", 1);
            //insert new elements into database
            for (int i = 0; i < itemObj.BibTexes.Count; i++)
            {
                BibTexStruct btStruct = (BibTexStruct)itemObj.BibTexes[i];
                XmlHelper.create(FILENAME).appendChild(getXPath() , btStruct.name, btStruct.value);
            }
        }
        /// <summary>
        /// update the belonging item object with data taken from database
        /// </summary>
        public void updateFromDB()
        {
            itemObj = selectFromDB();
        }

        /// <summary>
        /// get a Comment object given the id
        /// </summary>
        /// <param name="id">id of the object in XML file</param>
        /// <returns></returns>
        public Item selectFromDB()
        {
            //select all value of the this comment in database
            Item itemObject = new Item(itemObj.Id);            
            XPathNavigator navi = XmlHelper.create(FILENAME).getNavigator(getXPath());
            //<private>  
            navi.MoveToChild(XPathNodeType.Element);
            if (navi.InnerXml.Equals("0"))
                itemObject.BPrivate = false;
            else
                itemObject.BPrivate = true;
            //<category>
            navi.MoveToNext();
            itemObject.Category = CategoryProvider.create().getCatNameById(navi.InnerXml);
            //<..bibTexStruct>
            while (navi.MoveToNext())
            {
                BibTexStruct bStruct = new BibTexStruct();
                bStruct.name = navi.Name;
                bStruct.value = navi.InnerXml;
                itemObject.BibTexes.Add(bStruct);
            }
            return itemObject;
        }

        /// <summary>
        /// delete the item from the database
        /// </summary>
        public void deleteDB()
        {
            XmlHelper.create(FILENAME).deleteSelf(getXPath());
        }

        public static ArrayList getListOfAllItems()
        {
            ArrayList arlOfItemsId = getListOfAllItemsId();
            ArrayList arlOfItems = new ArrayList();
            if (arlOfItemsId == null)
            {
                return null;
            }
            else
            {
                foreach (Object itemId in arlOfItemsId)
                {
                    arlOfItems.Add(create(itemId.ToString()).selectFromDB());
                }
                return arlOfItems;
            }
            

        }
        public static ArrayList getListOfItemsByCategory(String catName)
        {
            ArrayList arlOfItemsId = getListOfItemsIdByCategory(catName);
            if (arlOfItemsId ==null )
            {
                return null;
            }
            else
            {
                ArrayList arlOfItems = null;

                if (arlOfItemsId != null)
                {
                    arlOfItems = new ArrayList();
                    foreach (Object itemId in arlOfItemsId)
                    {
                        arlOfItems.Add(create(itemId.ToString()).selectFromDB());
                    }
                }
                return arlOfItems;   
            } 
        }
        public static ArrayList getListOfItemsIdByCategory(String catName)
        {
            String catId = CategoryProvider.create().getCatIdByCatName(catName);
            if (catId.Equals(""))
            {
                return null;
            }
            else
            {
                ArrayList arlIDs = XmlHelper.create("item.xml").selectMultipleAttributeValues("/root/Item[contains(./category, '" + catId + "')]", "id");
                ArrayList arlResult = null;
                if (arlIDs !=null)
                {
                    arlResult = new ArrayList();
                    foreach (Object itemId in arlIDs)
                    {
                        arlResult.Add(itemId.ToString());
                    }                
                }

            return arlResult;
            }
          
        }
        public static ArrayList getListOfAllItemsId()
        {
            return XmlHelper.create("item.xml").selectMultipleAttributeValues("/root/Item","id");
        }

        public static void appendItem(Item itemObj)
        {
            //constuct xml text
            StringBuilder sb = new StringBuilder();
            sb.Append("<Item id='" + itemObj.Id + "'>");            
            if (itemObj.BPrivate)
                sb.Append("<private>1</private>");
            else
                sb.Append("<private>0</private>");
            sb.Append("<category>" + CategoryProvider.create().getCatIdByCatName(itemObj.Category) + "</category>");
            sb.Append("<title>" + ((BibTexStruct)itemObj.BibTexes[0]).value +"</title>");
            sb.Append("<author>" + ((BibTexStruct)itemObj.BibTexes[1]).value +"</author>");

            itemObj.BibTexes.RemoveRange(0,2);
            foreach (Object bts in itemObj.BibTexes)
            {
                String name = ((BibTexStruct)bts).name;
                String value = ((BibTexStruct)bts).value;
                sb.Append("<"+ name + ">"+ value +"</" + name + ">");
            }
            sb.Append("</Item>");
            //append
            XmlHelper.create("item.xml").appendChild("/root",sb.ToString());

        }
       
    }
}
